<template>
  <el-form-item class="edit-item edit-item-image image-pid-normal">
    <slot name="label">
      <label style="max-width: 95px; line-height: 16px;">
        {{label}}
        <TooltipsCommon v-if="!!tooltips" :tooltips="tooltips"></TooltipsCommon>
      </label>
    </slot>
      <div v-for="(item, index) in uploadFiles" :key="index" class="image-normal-item-box">
        <img class="image-normal-item-pic" :src="item.url" alt="">
        <el-upload
          :key="item.uid"
          name="pic"
          class="image-normal-item-rechange"
          :class="{'image-normal-content': false}"
          :action="action"
          :data="fileUploadData_"
          :show-file-list="false"
          :limit="1"
          :accept="accept"
          :auto-upload="true"
          :with-credentials="true"

          :before-upload="beforeUpload"
          :on-exceed="onExceed"
          :on-success="onSuccess(index, item)"
          :on-error="onError"
          :on-progress="onProgress">
            <template #default>
              <i class="image-normal-change">更换图片</i>
            </template>
        </el-upload>

        <div class="image-normal-actions">
          <el-button
            @click="onRemove(uploadFiles[index], uploadFiles)"
            class="image-normal-action-btn image-normal-delete"
            size="small"
            type="text"
            icon="Delete" circle>
          </el-button>

          <el-button
            @click="onPreview(uploadFiles[index])"
            class="image-normal-action-btn image-normal-preview"
            size="small"
            type="text"
            icon="Search" circle>
          </el-button>
        </div>
      </div>

    <div v-if="uploadFiles.length < limit" class="image-normal-add">
      <el-upload
        name="pic"
        :class="{'image-normal-content': false}"
        :action="action"
        :data="fileUploadData_"
        :show-file-list="false"
        :limit="initLimit"
        :accept="accept"
        list-type="picture-card"
        :auto-upload="true"
        :multiple="limit > 1"
        :with-credentials="true"

        :before-upload="beforeUpload"
        :on-exceed="onExceed"
        :on-success="onSuccess()"
        :on-error="onError"
        :on-progress="onProgress">
        <template #default>
          <el-icon class="image-normal-plus"><plus /></el-icon>
        </template>
      </el-upload>
    </div>

    <el-dialog v-model="dialogVisible">
      <img width="100%" :src="dialogImageUrl" alt="">
      <p class="image-normal-copy" @click.stop="clipboardCopy(dialogImageUrl)">{{dialogImageUrl}}</p>
    </el-dialog>
  </el-form-item>
</template>

<script>
  import { isNumber } from '@/utils/public';
  import { copyUtils } from '@/views/js/copy-utils';
  import { defineAsyncComponent } from 'vue';
  export default {
    name: 'imagePidNormal',
    mixins: [copyUtils],
    data() {
      return {
        uploadFiles: [],  // 暂存 files
        initLimit: 0,

        /* 预览 */
        dialogImageUrl: '',
        dialogVisible: false,

        /* 组件是否可用 */
        disabled: false,
      }
    },
    props: {
      label: String,  // 标签
      action: {       // 必须，上传地址
        type: String,
        default: '',
        // required: true
      },
      data: Object,   // 必须，上传配置参数
      size: Number,   // 文件大小限制，单位 ： k
      accept: String, // 文件类型，image/*, video/*, audio/*; 详见  <input type="file">
      tooltips: String,

      /* limit >= 1 => fileList */
      limit: Number,  // 文件个数限制，空 则不限制
      fileList: {     // 初始化 文件列表
        type: Array,
        default() {
          return [];
        }
      },

      /* 前/后缀 */
      prefix: {
        type: String,
        default: '',
      },
      suffix: {
        type: String,
        default: '',
      },
    },
    emits: ['change'],
    computed: {
      fileUploadData_() {
        return  _.cloneDeep(this.data);
      },
    },
    components: {
      TooltipsCommon: defineAsyncComponent(() => import('@/views/components/edit/tooltip-common.vue')),
    },
    beforeMount() {
      // init uploadFiles
      this.initUploadFiles();
    },
    methods: {
      /* init */
      initUploadFiles() {
        // 1. this.uploadFiles
        this.uploadFiles = this.fileList.map(item => {
          return {
            ...item,
            name: '',
            url: item.original_pic,
          };
        });

        // 2. initLimit
        this.initLimit = this.limit - this.uploadFiles.length;
      },

      /* life cycle */
      beforeUpload(file) {
        // 上传文件之前的钩子，参数为上传的文件，若返回 false 或者返回 Promise 且被 reject，则停止上传。

        // 1. size ： (单位 k)  this.size  >  file.size / 1024
        if(this.size < file.size / 1024) {
          this.$message({
            message: `警告哦，文件太大，超出 ${this.size} k`,
            type: 'warning'
          });
          return false;
        }

        // 2. 上传规则 data
        let fileSuffix = file.name.split(".")[1];  // 文件后缀
        let fileName = file.name.split(".")[0].split(' ').join('');  // 文件名称
        // file.filename = this.prefix + randomUploadFileName() + "" + randomUploadFileName() + this.suffix + "." + fileSuffix;
        // file.filename = this.prefix + encodeURIComponent(fileName) + this.suffix + "." + fileSuffix;
        file.filename = this.prefix + fileName + this.suffix + "." + fileSuffix;
        this.fileUploadData_.key = ( this.data ? this.data.key : '' ) + file.filename;
      },
      onExceed() {
        // 文件超出个数限制时的钩子
        this.$message({
          message: '警告哦，文件超出个数限制',
          type: 'warning'
        });
      },
      onPreview(file) {
        // 点击文件列表中已上传的文件时的钩子
        this.dialogImageUrl = file.url;
        this.dialogVisible = true;
      },
      onSuccess(index, oldFile) {
        return (response, file) => {
          // 文件上传成功时的钩子
          // console.log(response, file, fileList, index, oldFile);

          const bIsChange = isNumber( index ) && index >= 0;

          // 1. 预存 file ， 触发 uploadFiles 更新
          if( bIsChange ) this.uploadFiles.splice(index, 1, file);
          else this.uploadFiles.push(file);

          // 2. 处理 返回结果
          if( response.code > 0 ) {
            this.$message({
              message: '警告哦，文件上传失败',
              type: 'warning'
            });

            if( bIsChange ) this.uploadFiles.splice(index, 1, oldFile);
            else this.uploadFiles.pop();
          }
          else {
            const newFile = {
              name: file.name,
              size: file.size,
              uid: file.uid,
              url: response.data.original_pic,
              ...response.data,
            };

            if( bIsChange ) this.uploadFiles.splice(index, 1, newFile);
            else this.uploadFiles.splice(this.uploadFiles.length - 1, 1, newFile);
          }

          // 3. success 时 $emit change
          this.$emit('change', this.uploadFiles);
        }
      },
      onError(err) {
        // 文件上传失败时的钩子
        console.log('onError: ', err);
      },
      onProgress() {
        // 文件上传时的钩子
        // console.log('progress: ', event);
      },
      beforeRemove() {
        // 删除文件之前的钩子，参数为上传的文件和文件列表，若返回 false 或者返回 Promise 且被 reject，则停止删除。
        // return this.$confirm(`确定移除 ${ file.name }？`)
      },
      onRemove(file) {
        // 文件列表移除文件时的钩子
        // console.log('onRemove: ', file);

        // 1. remove
        if(this.uploadFiles.indexOf(file) > -1) this.uploadFiles.splice(this.uploadFiles.indexOf(file), 1);

        // 2. handler change
        this.$emit('change', this.uploadFiles);
      },
      /* Input handlerChange */
      handlerChange() {
        // <!-- 备用 -->
        // if(false) this.$emit('change', val);
      },

      /* 工具方法 */
      getStaticUrl(file) {
        if(!file.response || file.status != 'success') return file.url;
        let url = file.response.original_pic;
        return url;
      },
    },
    watch: {
      fileList: {
        immediate: true,
        handler() {
          // if(!this.bIsShowFileList) return;
          this.initUploadFiles();
        }
      },
    },
  }
</script>

<style lang="scss">
  .image-pid-normal {
    align-items: flex-start;

    .el-form-item__content {
      justify-content: flex-start;
      flex-wrap: wrap;
    }

    .image-normal-item-box {
      position: relative;
      margin: 5px 6px;
      width: 70px;
      height: 70px;
      background-color: #fbfdff;
      border: 1px dashed #c0ccda;
      border-radius: 6px;
      overflow: hidden;

      img.image-normal-item-pic {
        display: block;
        width: 100%;
        height: 100%;
        object-fit: contain;
      }

      .image-normal-item-rechange {
        position: absolute;
        bottom: 0;
        left: 0;
        width: 100%;
        height: 26px !important;
        background-color: rgba(0, 0, 0, 0);
        overflow: hidden;
        opacity: 0;
        transition: all .3s ease;

        .image-normal-change {
          position: absolute;
          bottom: 0;
          left: 0;
          width: 100%;
          text-align: center;
          padding: 0;
          color: #fff;
          line-height: 26px;
          font-size: 12px;
          font-style: normal;
          cursor: pointer;
        }
      }

      .image-normal-actions {
        position: absolute;
        display: flex;
        padding: 2px;
        width: 70px;
        height: 42px;
        left: 0;
        top: 0;
        background: rgba(255, 255, 255, 0);
        flex-direction: row-reverse;
        justify-content: space-around;
        align-items: flex-end;
        opacity: 0;
        transition: all .3s ease;

        .image-normal-action-btn {
          margin: 0 !important;
          background: rgba(0, 0, 0, .5);
          cursor: pointer;
          color: #fff;
        }
      }

      &:hover {
        .image-normal-item-rechange, .image-normal-actions {
          opacity: 1;
        }
        .image-normal-item-rechange {
          background: rgba(0, 0, 0, 0.6);
        }
        .image-normal-actions {
          background: rgba(255, 255, 255, 0.6);
        }
      }
    }

    .image-normal-add {
      position: relative;
      margin: 5px 6px;

      .el-upload-list {
        display: none;
      }
      .el-upload {
        position: relative;
        overflow: hidden;
        width: 70px !important;
        height: 70px !important;
      }

      .image-normal-plus {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
      }
    }
  }
</style>
